package tp.pr5.mv;

public class OperandStack extends Observable<OperandStack.Observer> {
	
	/* La clase OperandStack contiene un array de enteros que hará las funciones de la pila, un contador 
	 * y un tamaño que supondremos fijo.  */

	private int[] stack;
	private int sCounter;
	public static final int STACK_SIZE = 100;
	
	
	public OperandStack(){             // Constructor base.
		
		stack = new int[STACK_SIZE];
		sCounter = 0;
		 
	}
	
	public static interface Observer {
		
		public void onPop(int val);
		public void onPush(int val);
		public void onReset();
		
	}
	
	public void reset() {
		sCounter = 0;
		stack = new int[STACK_SIZE];
		for ( Observer o: observers ) o.onReset();
	}
	
	public boolean isEmpty() {         // Nos dice si la pila está vacía.
		
		return ( sCounter == 0 );
		
	}
	
	public int getStack( int i ) {          // Get del array de la pila.
		
		return stack[i];
		
	}
	 
	public int getCounter() {          // Get del contador de elementos.
		
		return sCounter;
		
	}

	
	
	public void incrementCounter() {          
		
		sCounter++;
		
	}
	
	public void pop() {                  
		
		if ( !this.isEmpty() )
		{
			for ( Observer o: observers )
				o.onPop( this.top() );
			sCounter--;                     // Quitamos la cima de la pila reduciendo el contador
		}
		
	}
	
	public int top() {                  
		
		if ( !this.isEmpty() )   
			return stack[sCounter-1];  // Simplemente devolvemos la cima de la pila.
		
		else 
			return 0;                  // Si la pila es vacía, devolvemos 0 por convenio.
	}
	
	public int subtop() {                  
		
		if ( sCounter >= 2 )   
			return stack[sCounter-2];  // Devolvemos la subcima de la pila.
		
		else 
			return 0;                 
	}
	
	
	public void push( int value ) {    
		
		stack[sCounter] = value;       // Añadimos a la cima el valor especificado.
		sCounter++;
		
		for ( Observer o: observers )
			o.onPush(value);
	}
	
	
}
